﻿using System;
using System.Collections.Generic;
using ch11.binary;
using ch11.binary.wasm_reader;
using ch11.cmd;
using ch11.instance;
using ch11.interpreter;

namespace ch11
{
    internal static class Program
    {
        public static void Main(params string[] args)
        {
            if (args.Length == 0)
            {
                Console.WriteLine("Usage: wasm-sharp [-d] filename");
                Environment.Exit(0);
            }

            if (args[0] == "-d")
            {
                var (module, err) = WasmReader.DecodeFile(args[1]);
                if (err == null)
                {
                    Dumper.Dump(module);
                }
                else
                {
                    Console.WriteLine(err);
                }
            }
            else
            {
                var (module, err) = WasmReader.DecodeFile(args[0]);
                if (err == null)
                {
                    InstantiateAndExecMainFunc(ref module);
                }
                else
                {
                    Console.WriteLine(err);
                }
            }
        }

        // private static void ExecMainFunc(ref Module module)
        // {
        //     var vm = new Vm(module);
        //     vm.InitMem();
        //     vm.InitGlobals();
        //     vm.InitFuncs();
        //     vm.InitTable();
        //     if (module.StartSec != 0)
        //     {
        //         Instr.Call(ref vm, module.StartSec);
        //     }
        //     else
        //     {
        //         Instr.Call(ref vm, GetMainFuncIdx(ref module));
        //     }
        //
        //     vm.Loop();
        // }

        static uint GetMainFuncIdx(ref Module module)
        {
            foreach (var exp in module.ExportSec)
            {
                if (exp.Desc.Tag == ConstData.ImportTagFunc && exp.Name == "main")
                {
                    return exp.Desc.Idx;
                }
            }

            Panic.Run("main func not found");
            return 0;
        }

        private static void InstantiateAndExecMainFunc(ref Module module)
        {
            var mm = new Dictionary<string, IModule> {{"env", Native.newEnv()}};
            var (m, err) = Vm.New(module, mm);
            if (err == null)
            {
                (_, err) = m.InvokeFunc("main");
            }

            if (err != null)
            {
                Console.WriteLine(err);
                Environment.Exit(1);
            }
        }
    }
}